package nio.GroupChat;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;

import lombok.extern.slf4j.Slf4j;

/**
 * @Author: Dgg
 * @Date: 2021/12/5 22:13
 */
@Slf4j
public class GroupChatServer {

	private Selector selector;

	private ServerSocketChannel listenChannel;

	private static final Integer port = 6667;

	// 初始化

	public GroupChatServer() {
		try {
			// 得到选择器
			selector = Selector.open();

			listenChannel = ServerSocketChannel.open();
			listenChannel.socket().bind(new InetSocketAddress(port));
			// 设置非阻塞
			listenChannel.configureBlocking(false);
			// 注册到selector
			listenChannel.register(selector, SelectionKey.OP_ACCEPT);

		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	// 监听代码
	public void listen() {
		System.out.println("监听线程:" + Thread.currentThread().getName());
		try {
			while (true) {
				if (selector.select() > 0) {
					Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
					while (iterator.hasNext()) {
						// 去除selection key
						SelectionKey key = iterator.next();
						// 处理链接
						if (key.isAcceptable()) {
							SocketChannel sc = listenChannel.accept();
							sc.configureBlocking(false);
							// 将改通道注册到selector
							sc.register(selector, SelectionKey.OP_READ);
							log.debug("提示：" + sc.getRemoteAddress() + "上线");
						}
						// 通道发生读取事件
						if (key.isReadable()) {
							// 处理读取
							getDataByChannel(key);
						}
						// 删除当前key,防止重复处理
						iterator.remove();
					}
				} else {
					log.debug("等待。。。。。。");
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	// 读取客户端消息
	public void getDataByChannel(SelectionKey key) {
		// 定义一个socketChannel
		SocketChannel socketChannel = null;
		try {
			socketChannel = (SocketChannel) key.channel();
			// 创建buffer
			ByteBuffer buffer = ByteBuffer.allocate(1024);
			int read = socketChannel.read(buffer);
			if (read > 0) {
				// 把缓冲区字符串输出
//				buffer.flip();
//				ByteBuffer allocate = ByteBuffer.allocate(buffer.limit());
//				allocate.put(buffer.get());
				buffer.limit(buffer.position());
				buffer.rewind();
				String s = new String(buffer.array());
				System.out.println("客户端消息:" + s);
				// 向其他客户端转发消息
				sendMsgOrther(s, socketChannel);

			}

		} catch (IOException e) {
			try {
				log.error(socketChannel.getRemoteAddress() + "离线");
				// 取消注册
				key.cancel();
				// 关闭通道
				socketChannel.close();
			} catch (IOException ioException) {
				ioException.printStackTrace();
			}
		}

	}

	// 转发消息给其他的通道
	private void sendMsgOrther(String msg, SocketChannel self) {
		log.debug("消息转发中");
		System.out.println("服务器转发给客户端线程" + Thread.currentThread().getName());
		try {
			// 遍历所有注册到selector 上的SocketChannel并排除自己
			for (SelectionKey key : selector.keys()) {
				// 通过key找到SocketChannel
				Channel channel = key.channel();

				// 排除自己
				if (channel instanceof SocketChannel && channel != self) {
					// 转型
					SocketChannel socketChannel = (SocketChannel) channel;
					// 将msg存储到buffer
					ByteBuffer wrap = ByteBuffer.wrap(msg.getBytes());
					// 将buffer写入通道
					socketChannel.write(wrap);
				}

			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		GroupChatServer server = new GroupChatServer();
		server.listen();

	}


}
